#include "llcc68_hal.h"

llcc68_hal_status_t llcc68_hal_write( const void* context, const uint8_t* command, const uint16_t command_length, const uint8_t* data, const uint16_t data_length )
{
	taskENTER_CRITICAL();
	while(LLCC68_BUSY_READ() != RESET);
	SPI1_CS_LOW();
	DMA1_CHANNEL2->dtcnt = (uint32_t)command_length;
	DMA1_CHANNEL2->maddr = (uint32_t)command;
	dma_channel_enable(DMA1_CHANNEL2, TRUE);
  while(dma_flag_get(DMA1_FDT2_FLAG) == RESET);
  dma_flag_clear(DMA1_FDT2_FLAG);
	dma_channel_enable(DMA1_CHANNEL2, FALSE);
	
	if(data_length)
	{
		DMA1_CHANNEL2->dtcnt = (uint32_t)data_length;
		DMA1_CHANNEL2->maddr = (uint32_t)data;
		dma_channel_enable(DMA1_CHANNEL2, TRUE);
		while(dma_flag_get(DMA1_FDT2_FLAG) == RESET);
		dma_flag_clear(DMA1_FDT2_FLAG);
		dma_channel_enable(DMA1_CHANNEL2, FALSE);
	}
	
	while(spi_i2s_flag_get(SPI1, SPI_I2S_BF_FLAG) != RESET);
	SPI1_CS_HIGH();
	delay_us_rtos(2);
	while(LLCC68_BUSY_READ() != RESET);
	taskEXIT_CRITICAL();
	return LLCC68_HAL_STATUS_OK;
}

llcc68_hal_status_t llcc68_hal_read( const void* context, const uint8_t* command, const uint16_t command_length, uint8_t* data, const uint16_t data_length )
{
	taskENTER_CRITICAL();
	while(LLCC68_BUSY_READ() != RESET);
	
	uint8_t cmd_buf[16];
	spi_enable(SPI1, FALSE);
	spi_enable(SPI1, TRUE);
	SPI1_CS_LOW();
	DMA1_CHANNEL1->dtcnt = (uint32_t)command_length;
	DMA1_CHANNEL1->maddr = (uint32_t)cmd_buf;
	DMA1_CHANNEL2->dtcnt = (uint32_t)command_length;
	DMA1_CHANNEL2->maddr = (uint32_t)command;
	dma_channel_enable(DMA1_CHANNEL1, TRUE);
	dma_channel_enable(DMA1_CHANNEL2, TRUE);
	// wait flag
  while(dma_flag_get(DMA1_FDT2_FLAG) == RESET);
  dma_flag_clear(DMA1_FDT2_FLAG);
	while(dma_flag_get(DMA1_FDT1_FLAG) == RESET);
	dma_flag_clear(DMA1_FDT1_FLAG);
	dma_channel_enable(DMA1_CHANNEL1, FALSE);
	dma_channel_enable(DMA1_CHANNEL2, FALSE);
	while(spi_i2s_flag_get(SPI1, SPI_I2S_BF_FLAG) != RESET);

	uint8_t nop_cmd[255] = { 0x00 };
	DMA1_CHANNEL1->dtcnt = (uint32_t)data_length;
	DMA1_CHANNEL1->maddr = (uint32_t)data;
	DMA1_CHANNEL2->dtcnt = (uint32_t)data_length;
	DMA1_CHANNEL2->maddr = (uint32_t)nop_cmd;
	dma_channel_enable(DMA1_CHANNEL1, TRUE);
	dma_channel_enable(DMA1_CHANNEL2, TRUE);
	while(dma_flag_get(DMA1_FDT1_FLAG) == RESET);
	dma_flag_clear(DMA1_FDT1_FLAG);
	while(dma_flag_get(DMA1_FDT2_FLAG) == RESET);
	dma_flag_clear(DMA1_FDT2_FLAG);
	
	dma_channel_enable(DMA1_CHANNEL1, FALSE);
	dma_channel_enable(DMA1_CHANNEL2, FALSE);
	
	while(spi_i2s_flag_get(SPI1, SPI_I2S_BF_FLAG) != RESET);
	SPI1_CS_HIGH();
	delay_us_rtos(2);
	while(LLCC68_BUSY_READ() != RESET);
	taskEXIT_CRITICAL();
	return LLCC68_HAL_STATUS_OK;
}

llcc68_hal_status_t llcc68_hal_reset( const void* context )
{
	taskENTER_CRITICAL();
	LLCC68_RST_HIGH();
	LLCC68_RST_LOW();
	//delay_ms(1);
	delay_ms_rtos(1);
	LLCC68_RST_HIGH();
	delay_us_rtos(2);
	while(LLCC68_BUSY_READ() != RESET);
	taskEXIT_CRITICAL();
	return LLCC68_HAL_STATUS_OK;
}

llcc68_hal_status_t llcc68_hal_wakeup( const void* context )
{
	taskENTER_CRITICAL();
	SPI1_CS_LOW();
	//delay_us(200);
	delay_us_rtos(200);
	SPI1_CS_HIGH();
	taskEXIT_CRITICAL();
	return LLCC68_HAL_STATUS_ERROR;
}